//: Playground - noun: a place where people can play

import UIKit
//: # swfit 读书笔记


//: ## 存储属性: 一个存储属性就是存储在特定类或结构体实例里的一个常量或变量。存储属性,可以是变量存储属性（用关键字 var 定义），也可以是常量存储属性（用关键字 let 定义）。

//: ### 常量结构体的存储属性 : 如果创建了一个结构体的实例并将其赋值给一个常量，则无法修改该实例的任何属性，即使有属性被声明为变量也不行
print("_____________________常量结构体的存储属性_____________________________")
struct FieldMaxLength{
    var max:Int
    let min:Int
}

let filedH = FieldMaxLength (max: 3, min: 0)

//: filedH.max = 7;  这个赋值会报错

//: ### 延迟存储属性(懒加载):延迟存储属性是指当第一次被调用的时候才会计算其初始值的属性。在属性声明前使用 lazy var 来标示一个延迟存储属性
//: ### 如果一个被标记为 lazy 的属性在没有初始化时就同时被多个线程访问，则无法保证该属性只会被初始化一次。
print("_____________________延迟存储属性_____________________________")

//: ## 计算属性: 除普通存储属性外，类、结构体和枚举可以定义计算属性，算属性不直接存储值，而是提供一个 getter 和一个可选的 setter，来间接获取和设置其他属性或变量的值
print("_____________________计算属性_____________________________")
struct Point{
    var  x = 0.0 , y = 0.0
}

struct Size {
    var width = 0.0, heigth = 0.0
}

struct Rect {
    var origin = Point()
    var size = Size ()
    var name: String? {
        get {
            return self.name
        }
        set {
            name = newValue
        }
    }
    
    var center:Point{
        
        set(newCenter){
            origin.x = newCenter.x - (size.width/2)
            origin.y = newCenter.y - (size.heigth/2)
        }
        
        get{
            let centerX = origin.x + (size.width/2)
            let centerY = origin.y + (size.heigth/2)
            return Point (x: centerX, y: centerY)
        }
    }
}

//:### 简化 setter 声明:如果计算属性的 setter 没有定义表示新值的参数名，则可以使用默认名称 newValue
struct AlternativeRect {
    var origin = Point()
    var size = Size ()
    var center:Point{
        
        set{
            origin.x = newValue.x - (size.width/2)
            origin.y = newValue.y - (size.heigth/2)
        }
        
        get{
            let centerX = origin.x + (size.width/2)
            let centerY = origin.y + (size.heigth/2)
            return Point (x: centerX, y: centerY)
        }
    }
    
}

//: ### 只读计算型属性:必须使用 var 关键字定义计算属性、只读计算属性的声明可以去掉 get 关键字和花括号
print("_____________________只读计算型属性_____________________________")
struct Cuboid {
    var volume:Double{
        return 3.1415
    }
}

//: ## 属性观察器:每次属性被设置值的时候都会调用属性观察器，即使新值和当前值相同的时候也不例外
//: ### willSet 在新的值被设置之前调用,如果不指定则参数仍然可用，这时使用默认名称 newValue
//: ### didSet 在新的值被设置之后立即调用,将旧的属性值作为参数传入，可以为该参数命名或者使用默认参数名 oldValue
//: ### 父类的属性在子类的构造器中被赋值时，它在父类中的 willSet 和 didSet 观察器会被调用，随后才会调用子类的观察器。在父类初始化方法调用之前，子类给属性赋值时，观察器不会被调用
print("_____________________ 属性观察器 willSet didSet _____________________________")
class StepCounter{
    var totalStep:Int = 0{
        willSet(newTotalSteps){
            print("新走了-\(newTotalSteps)")
        }
        
        didSet{
            if totalStep > oldValue {
                print("多走了-\(totalStep - oldValue)")
            }
        }
    }
}

let stepper = StepCounter ()
stepper.totalStep = 3;
stepper.totalStep = 6;

//: ## 全局变量和局部变量:这个不知道可以去死了

//: ##  类型属性
//: ### 类型属性语法:使用关键字 static 来定义类型属性。在为类定义计算型类型属性时，可以改用关键字 class 来支持子类对父类的实现进行重写
print("_____________________ 类型属性 _____________________________")

struct someStruct{
    static var storedTypeValue = "some struct"
    static var storedNum:Int{
        return 1
    }
}
print("someStruct - \(someStruct.storedTypeValue)")
enum someEnum{
    static var storedTypeValue = "some enum"
    static var storedNum:Int{
        return 2
    }
}

print("someEnum - \(someEnum.storedTypeValue)")
class someClass{
    static var storedTypeValue = "some struct"
    static var storedNum:Int{
        return 3
    }
    class var subClassOverried:Int{
        return 110
    }
}
print("someClass - \(someClass.storedTypeValue)")
